package com.seal.tsms.base.dao;

import freemarker.cache.StringTemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.boot.cfgxml.internal.JaxbCfgProcessor;
import org.springframework.http.converter.HttpMessageConversionException;
import org.springframework.ui.freemarker.FreeMarkerConfigurationFactoryBean;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAnyElement;
import java.io.*;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * Created by seal.jing on 2015/12/25.
 */
public class QueryParser {
    public static String getQueryString(String name,Map<String,?> paramMap) throws Exception {
        String queryString=null;

        Configuration cfg = new Configuration(Configuration.VERSION_2_3_23);
        //字符串模板加载器
        StringTemplateLoader stringTemplateLoader = new StringTemplateLoader();
        //获得hql或sql模板
        String queryStringTemplate = getQueryStringTemplate(name);
        if(queryStringTemplate==null || "".equals(queryStringTemplate)){
            throw new Exception("查询名称为：queryName："+name+"的查询不存在");
        }
        stringTemplateLoader.putTemplate(name, queryStringTemplate);

        cfg.setTemplateLoader(stringTemplateLoader);
        cfg.setDefaultEncoding("UTF-8");
        Template template = cfg.getTemplate(name,"UTF-8");

        StringWriter writer = new StringWriter();

        template.process(paramMap, writer);




        return queryString=writer.toString().trim();
    }
    public static String getQueryStringTemplate(String name){

        return allQueryTemplateMap.get(name);
    }
    private static  Map<String,String> allQueryTemplateMap;
    public Map<String,String> getAllQueryTemplateMap(){
        return allQueryTemplateMap;
    }
    public static void createAllQueryTemplateMap() throws Exception {

        allQueryTemplateMap=new HashMap<String, String>();
        URL url = QueryParser.class.getResource(Querys.QUERY_FILE_PATH);
        InputStream in = new FileInputStream(new File(url.toURI()));
        QueryFiles queryFile = fromXml(IOUtils.toString(in,"UTF-8"),QueryFiles.class);
        List<QueryFiles.Query> queryFileList = queryFile.getQuery();
        if(queryFileList!=null){
            for(QueryFiles.Query query : queryFileList){
                String filePath = query.getFile();

                //根据filePath读取所有的*.query.xml
                url = QueryParser.class.getResource("/"+filePath);
                in = new FileInputStream(new File(url.toURI()));
                if(in==null){
                    throw new Exception("文件："+filePath+"不存在");
                }
                QueryMapping queryMapping = fromXml(IOUtils.toString(in,"UTF-8"),QueryMapping.class);

                //将*.query.xml中的所有queryName和hql语句、sql语句放入map
                for(QueryMapping.Query q : queryMapping.getQuery()){
                    String queryName = q.getName();
                    if(allQueryTemplateMap.containsKey(queryName)){
                        throw new Exception("外部查询语句的queryName重复，queryName："+queryName);
                    }
                    String hql = q.getHql();
                    String sql = q.getSql();

                    if(StringUtils.isNotBlank(hql) && StringUtils.isNotBlank(sql)){
                        throw new Exception("外部查询语句的hql语句和sql不可同时出现在同一个query中，queryName："+queryName);
                    }
                    if(StringUtils.isNotBlank(hql)){
                        allQueryTemplateMap.put(queryName,hql);
                    }else if(StringUtils.isNotBlank(sql)){
                        allQueryTemplateMap.put(queryName,sql);
                    }else{
                        throw new Exception("外部查询语句的hql或sql不存在，queryName："+queryName);
                    }
                }
            }
        }
        IOUtils.closeQuietly(in);
        //上线后，赋给静态变量
        //ALL_QUERY_MAP = queryTemptateMap;



    }
    public static <T> T fromXml(String xml,Class<T> clazz) throws Exception {
        StringReader reader = new StringReader(xml);
        return (T) createUnmarshaller(clazz).unmarshal(reader);
    }

    private static Unmarshaller createUnmarshaller(Class clazz) throws Exception {
        JAXBContext jaxbContext = getJaxbContext(clazz);
        return jaxbContext.createUnmarshaller();

    }

    private static ConcurrentMap<Class, JAXBContext> jaxbContexts = new ConcurrentHashMap<Class, JAXBContext>();
    private static JAXBContext getJaxbContext(Class clazz) {
        JAXBContext jaxbContext = jaxbContexts.get(clazz);
        if (jaxbContext == null) {
            try {
                jaxbContext = JAXBContext.newInstance(clazz, CollectionWrapper.class);
                jaxbContexts.putIfAbsent(clazz, jaxbContext);
            } catch (JAXBException ex) {
                throw new HttpMessageConversionException("Could not instantiate JAXBContext for class [" + clazz
                        + "]: " + ex.getMessage(), ex);
            }
        }
        return jaxbContext;
    }
    /**
     * 封装Root Element 是 Collection的情况.
     */
    public static class CollectionWrapper {
        @XmlAnyElement
        protected Collection<?> collection;
    }
    public static void main(String[] args) throws Exception {
        createAllQueryTemplateMap();
        Map<String ,?> params=new HashMap<String, Object>();
        String hql=getQueryString("system.test",params);
        System.out.println(hql);

    }
}
